package com.scholarship.system.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.scholarship.system.common.constants.SystemConstants;
import com.scholarship.system.common.dto.LoginRequest;
import com.scholarship.system.common.dto.LoginResponse;
import com.scholarship.system.common.dto.Result;
import com.scholarship.system.common.exception.BusinessException;
import com.scholarship.system.common.util.JwtUtil;
import com.scholarship.system.entity.Student;
import com.scholarship.system.entity.Teacher;
import com.scholarship.system.entity.User;
import com.scholarship.system.mapper.StudentMapper;
import com.scholarship.system.mapper.TeacherMapper;
import com.scholarship.system.mapper.UserMapper;
import com.scholarship.system.service.UserService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.authentication.BadCredentialsException;

import java.util.List;

/**
 * 用户服务实现类
 */
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {

    private static final Logger log = LoggerFactory.getLogger(UserServiceImpl.class);

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private StudentMapper studentMapper;

    @Autowired
    private TeacherMapper teacherMapper;

    private AuthenticationManager authenticationManager;

    @Autowired
    @Lazy
    public void setAuthenticationManager(AuthenticationManager authenticationManager) {
        this.authenticationManager = authenticationManager;
    }

    @Autowired
    private UserDetailsService userDetailsService;

    @Autowired
    private JwtUtil jwtUtil;

    @Autowired
    private PasswordEncoder passwordEncoder;

    @Override
    public Result<LoginResponse> login(LoginRequest loginRequest) {
        log.info("处理登录请求: {}", loginRequest.getUsername());
        try {
            // 验证用户是否存在
            User user = getByUsername(loginRequest.getUsername());
            if (user == null) {
                log.error("登录失败: 用户不存在, username={}", loginRequest.getUsername());
                throw new BusinessException("用户不存在");
            }

            // 只允许导师角色登录
            if (!SystemConstants.ROLE_TEACHER.equals(user.getRole())) {
                log.error("登录失败: 非导师角色, username={}, 实际角色={}",
                        loginRequest.getUsername(), user.getRole());
                throw new BusinessException("只允许导师账号登录系统");
            }

            log.info("开始认证用户: {}", loginRequest.getUsername());
            // 认证
            Authentication authentication = null;
            try {
                authentication = authenticationManager.authenticate(
                        new UsernamePasswordAuthenticationToken(loginRequest.getUsername(),
                                loginRequest.getPassword()));
            } catch (BadCredentialsException e) {
                log.error("登录失败: 密码错误, username={}", loginRequest.getUsername(), e);
                throw new BusinessException("密码错误");
            } catch (Exception e) {
                log.error("登录认证过程发生异常", e);
                throw e;
            }

            SecurityContextHolder.getContext().setAuthentication(authentication);

            // 生成token
            UserDetails userDetails = userDetailsService.loadUserByUsername(loginRequest.getUsername());
            String token = jwtUtil.generateToken(userDetails);
            log.info("用户登录成功并生成token: {}", loginRequest.getUsername());

            // 构造返回结果
            LoginResponse loginResponse = new LoginResponse();
            loginResponse.setToken(token);

            LoginResponse.UserInfo userInfo = new LoginResponse.UserInfo();
            BeanUtils.copyProperties(user, userInfo);
            loginResponse.setUserInfo(userInfo);

            return Result.success(loginResponse);

        } catch (BusinessException be) {
            return Result.error(be.getMessage());
        } catch (Exception e) {
            log.error("登录过程发生未预期异常", e);
            return Result.error("系统错误，请稍后重试");
        }
    }

    @Override
    public Result<LoginResponse.UserInfo> getUserInfo(String username) {
        User user = getByUsername(username);
        if (user == null) {
            return Result.error("用户不存在");
        }

        LoginResponse.UserInfo userInfo = new LoginResponse.UserInfo();
        BeanUtils.copyProperties(user, userInfo);

        return Result.success(userInfo);
    }

    @Override
    public User getByUsername(String username) {
        LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(User::getUsername, username);
        return userMapper.selectOne(wrapper);
    }

    @Override
    public List<User> getUserList(String role, String keyword) {
        LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();

        // 如果指定了角色，按角色筛选
        if (StringUtils.hasText(role)) {
            wrapper.eq(User::getRole, role);
        }

        // 如果有关键字，则按用户名或姓名模糊查询
        if (StringUtils.hasText(keyword)) {
            wrapper.and(w -> w.like(User::getUsername, keyword)
                    .or()
                    .like(User::getName, keyword));
        }

        // 排序
        wrapper.orderByDesc(User::getCreateTime);

        return userMapper.selectList(wrapper);
    }

    @Override
    @Transactional
    public void addUser(User user) {
        // 检查用户名是否已存在
        User existUser = getByUsername(user.getUsername());
        if (existUser != null) {
            throw new BusinessException("用户名已存在");
        }

        // 设置默认密码
        if (!StringUtils.hasText(user.getPassword())) {
            user.setPassword(SystemConstants.DEFAULT_PASSWORD);
        }
        // 不再加密密码
        // user.setPassword(passwordEncoder.encode(user.getPassword()));

        // 保存用户
        userMapper.insert(user);

        // 不再自动创建Teacher记录，避免数据库缺少必填字段的错误
        // 这些记录将在注册过程中通过前端单独调用Teacher控制器来创建
    }

    @Override
    @Transactional
    public void updateUser(User user) {
        // 检查用户是否存在
        User existUser = userMapper.selectById(user.getId());
        if (existUser == null) {
            throw new BusinessException("用户不存在");
        }

        // 如果修改了用户名，检查新用户名是否已存在
        if (!existUser.getUsername().equals(user.getUsername())) {
            User usernameUser = getByUsername(user.getUsername());
            if (usernameUser != null && !usernameUser.getId().equals(user.getId())) {
                throw new BusinessException("用户名已存在");
            }
        }

        // 不更新密码
        user.setPassword(null);

        // 更新用户
        userMapper.updateById(user);
    }

    @Override
    @Transactional
    public void deleteUser(Long id) {
        // 检查用户是否存在
        User user = userMapper.selectById(id);
        if (user == null) {
            throw new BusinessException("用户不存在");
        }

        // 根据角色，删除对应的学生或教师记录
        if (SystemConstants.ROLE_STUDENT.equals(user.getRole())) {
            LambdaQueryWrapper<Student> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(Student::getUserId, id);
            studentMapper.delete(wrapper);
        } else if (SystemConstants.ROLE_TEACHER.equals(user.getRole())) {
            LambdaQueryWrapper<Teacher> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(Teacher::getUserId, id);
            teacherMapper.delete(wrapper);
        }

        // 删除用户
        userMapper.deleteById(id);
    }

    @Override
    public void resetPassword(Long id) {
        // 检查用户是否存在
        User user = userMapper.selectById(id);
        if (user == null) {
            throw new BusinessException("用户不存在");
        }

        // 重置密码 - 使用明文
        User updateUser = new User();
        updateUser.setId(id);
        updateUser.setPassword(SystemConstants.DEFAULT_PASSWORD);
        // 不再加密
        // updateUser.setPassword(passwordEncoder.encode(SystemConstants.DEFAULT_PASSWORD));

        userMapper.updateById(updateUser);
    }
}